package org.infinispan.server.test.util.osgi;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Enumeration;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;
/**
* Class copied from JBoss Fuse project and modified.
*/
public final class ServiceLocator {
public static final Long DEFAULT_TIMEOUT = 60000L;
private ServiceLocator() {
//Utility Class
}
public static <T> T getOsgiService(Class<T> type, long timeout) {
return getOsgiService(type, null, timeout);
}
public static <T> T getOsgiService(Class<T> type) {
return getOsgiService(type, null, DEFAULT_TIMEOUT);
}
public static <T> T getOsgiService(Class<T> type, String filter) {
return getOsgiService(type, filter, DEFAULT_TIMEOUT);
}
public static <T> T getOsgiService(Class<T> type, String filter, long timeout) {
BundleContext bundleContext = getBundleContext();
ServiceTracker tracker = null;
try {
String flt;
if (filter != null) {
if (filter.startsWith("(")) {
flt = "(&(" + Constants.OBJECTCLASS + "=" + type.getName() + ")" + filter + ")";
} else {
flt = "(&(" + Constants.OBJECTCLASS + "=" + type.getName() + ")(" + filter + "))";
}
} else {
flt = "(" + Constants.OBJECTCLASS + "=" + type.getName() + ")";
}
Filter osgiFilter = FrameworkUtil.createFilter(flt);
tracker = new ServiceTracker(bundleContext, osgiFilter, null);
tracker.open(true);
// Note that the tracker is not closed to keep the reference
// This is buggy, as the service reference may change i think
Object svc = type.cast(tracker.waitForService(timeout));
if (svc == null) {
Dictionary<String, String> dic = bundleContext.getBundle().getHeaders();
System.err.println("Test bundle headers: " + explode(dic));
for (ServiceReference ref : asCollection(bundleContext.getAllServiceReferences(null, null))) {
System.err.println("ServiceReference: " + ref);
}
for (ServiceReference ref : asCollection(bundleContext.getAllServiceReferences(null, flt))) {
System.err.println("Filtered ServiceReference: " + ref);
}
throw new RuntimeException("Gave up waiting for service " + flt);
}
return type.cast(svc);
} catch (InvalidSyntaxException e) {
throw new IllegalArgumentException("Invalid filter", e);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
/**
* Returns the bundle context.
*/
private static BundleContext getBundleContext() {
return FrameworkUtil.getBundle(ServiceLocator.class).getBundleContext();
}
/**
* Explode the dictionary into a ,-delimited list of key=value pairs
*/
private static String explode(Dictionary<String, String> dictionary) {
Enumeration<String> keys = dictionary.keys();
StringBuilder result = new StringBuilder();
while (keys.hasMoreElements()) {
Object key = keys.nextElement();
result.append(String.format("%s=%s", key, dictionary.get(key)));
if (keys.hasMoreElements()) {
result.append(", ");
}
}
return result.toString();
}
/**
* Provides an iterable collection of references, even if the original array is null
*/
private static Collection<ServiceReference> asCollection(ServiceReference[] references) {
return references != null ? Arrays.asList(references) : Collections.<ServiceReference>emptyList();
}
}